<script setup lang="ts">
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons-vue'
import type { UploadChangeParam, UploadProps } from 'ant-design-vue'
import type { Rule } from 'ant-design-vue/es/form'
import type { DeptResp } from '~/api/setting/model/dept.ts'
import {
  emailValidator,
  mobileNoValidator,
  nameValidator,
  passwordValidator,
  usernameValidator,
} from '~/utils/form-validator.ts'
import type { RoleResp } from '~/api/setting/model/role.ts'
import type { Page, Query } from '~/api/base/base-model.ts'
import { queryRolePageApi } from '~/api/setting/role.ts'
import { queryDeptTreeListApi } from '~/api/setting/dept.ts'
import type { MenuResp } from '~/api/setting/model/menu.ts'
import { queryMenuTreeListApi } from '~/api/setting/menu.ts'
import { MICRO_SERVICE_FILE_UPLOAD_AUTH } from '~/constants/service-constant.ts'
import { createUserApi, modifyUserApi } from '~/api/setting/user.ts'
import { useAuthorization } from '~/composables/authorization.ts'
import type { UserReq } from '~/api/setting/model/user.ts'

const props = defineProps({
  userData: Object,
  optType: {
    type: String,
    default: 'create',
  },

})

const emits = defineEmits(['onSaveSuccess'])

const token = useAuthorization()
const message = useMessage()

const uploadApi = shallowRef<string>(`${window.location.origin}${MICRO_SERVICE_FILE_UPLOAD_AUTH}?bucketName=ums-bucket`)

const uploadLoading = shallowRef(false)
const imageUrl = shallowRef<string>('')
const iconFileId = shallowRef<string>('')
const fileList = ref([])

const userReq = ref<UserReq>({
  username: undefined,
  password: undefined,
  realName: undefined,
  nickName: undefined,
  mobileNo: undefined,
  email: undefined,
  roleIds: [],
  deptIds: [],
  homeMenuId: undefined,
  note: undefined,
})

const userCreateFormRef = ref()
const rules: Record<string, Rule[]> = {
  username: [
    { required: true, message: '请输入用户账号' },
    { validator: usernameValidator, trigger: 'blur' },
  ],
  password: [
    { required: true, message: '请输入用户密码' },
    { validator: passwordValidator, trigger: 'blur' },
  ],
  realName: [
    { required: true, message: '请输入用户姓名' },
    { validator: nameValidator, trigger: 'blur' },
  ],
  mobileNo: [
    { required: true, message: '请输入手机号' },
    { validator: mobileNoValidator, trigger: 'blur' },
  ],
  email: [
    { required: true, message: '请输入用户邮箱' },
    { validator: emailValidator, trigger: 'blur' },
  ],
  roleIds: [
    {
      type: 'array',
      required: true,
      message: '请选择用户角色',
      trigger: 'change',
    },
  ],
  deptIds: [
    {
      type: 'array',
      required: true,
      message: '请选择所属部门',
      trigger: 'change',
    },
  ],
  homeMenuId: [
    { required: true, message: '请选择工作台' },
  ],
}

const roleListData = shallowRef<RoleResp[]>()

/**
 * 初始化角色
 */
async function init() {
  if (props.userData) {
    userReq.value = props.userData
    imageUrl.value = props.userData.iconFileUrl
  }
}
/**
 * 初始化角色
 */
async function initRoles() {
  const query: Query<any> = {
    size: 1000,
  }
  const rolePage: Page<RoleResp> = await queryRolePageApi(query)
  roleListData.value = rolePage?.records
}

const deptTreeData = shallowRef<DeptResp[]>()

/**
 * 初始化部门
 */
async function initDeptTree() {
  deptTreeData.value = await queryDeptTreeListApi()
}

const menuTreeData = shallowRef<MenuResp[]>()

/**
 * 初始化菜单
 */
async function initMenuTree() {
  menuTreeData.value = await queryMenuTreeListApi()
}

// region 上传头像

function beforeUpload(file?: UploadProps['fileList'][number]) {
  const isJpgOrPng = file.type === 'image/png' || file.type === 'image/jpeg'
  if (!isJpgOrPng) {
    message.warning('请上传图片文件')
    return isJpgOrPng
  }

  const isLt2M = file.size / 1024 / 1024 < 2
  if (!isLt2M) {
    message.warning('请上传图片文件大小小于2BM')
  }

  return isJpgOrPng && isLt2M
}

function handleChange(info: UploadChangeParam) {
  if (info.file.status === 'uploading') {
    uploadLoading.value = true
  }

  if (info.file.status === 'done') {
    if (
      info.file.response
      && info.file.response.result
      && info.file.response.result.fileUrl
    ) {
      imageUrl.value = info.file.response?.result?.fileUrl
      iconFileId.value = info.file.response?.result?.fileId
    }
    uploadLoading.value = false
  }
  if (info.file.status === 'error') {
    uploadLoading.value = false
    message.error('上传图片文件失败')
  }
}

// endregion

const confirmLoading = shallowRef(false)

async function onSaveUser() {
  if (props.optType === 'create') {
    await onCreateUser()
  } else {
    await onEditUser()
  }
}

/**
 *  添加用户
 */
async function onCreateUser() {
  userCreateFormRef.value
    .validate()
    .then(() => {
      confirmLoading.value = true
      const file: any = fileList.value[0]
      userReq.value.icon = file?.response?.result?.fileId
      createUserApi(userReq.value).then((response) => {
        if (response) {
          message.success('新建成功')
          emits('onSaveSuccess', 'create')
        }
      }).finally(() => {
        confirmLoading.value = false
        close()
      })
    })
    .catch(() => {
      console.log('userCreateFormRef::error')
    })
}

/**
 *  编辑用户
 */
async function onEditUser() {
  userCreateFormRef.value
    .validate()
    .then(() => {
      confirmLoading.value = true
      const file: any = fileList.value[0]
      userReq.value.icon = file?.response?.result?.fileId
      modifyUserApi(userReq.value).then((response) => {
        if (response) {
          message.success('修改成功')
          emits('onSaveSuccess', 'edit')
        }
      }).finally(() => {
        confirmLoading.value = false
        close()
      })
    })
    .catch(() => {
      console.log('userCreateFormRef::error')
    })
}

onMounted(() => {
  init()
  initRoles()
  initDeptTree()
  initMenuTree()
})
</script>

<template>
  <a-modal title="编辑用户" width="600px" :confirm-loading="confirmLoading" @ok="onSaveUser">
    <a-space direction="vertical" size="large" class="w-full">
      <a-form
        ref="userCreateFormRef"
        :model="userReq"
        :rules="rules"
        :label-col="{ span: 4 }"
        :wrapper-col="{ span: 14 }"
        layout="horizontal"
      >
        <a-form-item label="头像">
          <a-upload
            v-model:file-list="fileList"
            name="file"
            list-type="picture-card"
            class="avatar-uploader"
            :show-upload-list="false"
            :action="uploadApi"
            :headers="{ Authorization: token }"
            :before-upload="beforeUpload"
            @change="handleChange"
          >
            <img v-if="imageUrl" class="avatar-uploader-img" :src="imageUrl" alt="avatar">
            <div v-else>
              <LoadingOutlined v-if="uploadLoading" />
              <PlusOutlined v-else />
              <div class="ant-upload-text">
                上传
              </div>
            </div>
          </a-upload>
        </a-form-item>
        <a-form-item name="username" label="账号">
          <a-input v-model:value="userReq.username" placeholder="请输入用户账号" allow-clear />
        </a-form-item>
        <a-form-item v-if="optType === 'create'" name="password" label="密码">
          <a-input-password v-model:value="userReq.password" placeholder="请输入用户密码" allow-clear />
        </a-form-item>
        <a-form-item name="realName" label="姓名">
          <a-input v-model:value="userReq.realName" placeholder="请输入用户账号" allow-clear />
        </a-form-item>
        <a-form-item name="mobileNo" label="手机号">
          <a-input v-model:value="userReq.mobileNo" placeholder="请输入手机号" allow-clear />
        </a-form-item>
        <a-form-item name="email" label="邮箱">
          <a-input v-model:value="userReq.email" placeholder="请输入用户邮箱" allow-clear />
        </a-form-item>
        <a-form-item name="roleIds" label="角色">
          <a-select
            v-model:value="userReq.roleIds"
            mode="multiple"
            placeholder="请选择用户角色"
            option-filter-prop="label"
            show-search
            allow-clear
          >
            <a-select-option
              v-for="item in roleListData"
              :key="item.id"
              :label="item.roleName"
            >
              {{
                item.roleName
              }}
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item name="deptIds" label="所属部门">
          <a-tree-select
            v-model:value="userReq.deptIds"
            tree-checkable
            tree-default-expand-all
            placeholder="请选择所属部门"
            :tree-data="deptTreeData"
            :field-names="{ value: 'id', label: 'deptName' }"
            tree-node-filter-prop="label"
            show-search
            allow-clear
          />
        </a-form-item>
        <a-form-item name="homeMenuId" label="首页">
          <a-tree-select
            v-model:value="userReq.homeMenuId"
            tree-default-expand-all
            placeholder="请选择工作台"
            :tree-data="menuTreeData"
            :field-names="{ value: 'id', label: 'menuTitle' }"
            tree-node-filter-prop="label"
            show-search
            allow-clear
          />
        </a-form-item>
        <a-form-item name="note" label="备注">
          <a-textarea
            v-model:value="userReq.note"
            :rows="4"
            placeholder="请输入备注"
            allow-clear
          />
        </a-form-item>
      </a-form>
    </a-space>
  </a-modal>
</template>

<style lang="less" scoped>
.avatar-uploader {
  .ant-upload {
    width: 128px;
    height: 128px;
  }
}

.avatar-uploader-img {
  width: 100px;
  height: 100px;
  border-radius: 8px;
}

.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}

.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
</style>
